#ifndef __Y64_TASK_H__
#define __Y64_TASK_H__

#include "lib.h"
#include "memory.h"
#include "cpu.h"
#include "ptrace.h"

#define STACK_SIZE (32 * 1024)              // 栈大小32KB

#define PF_KTHREAD (1 << 0)

#define TASK_RUNNING            (1 << 0)
#define TASK_INTERRUPTIBLE      (1 << 1)
#define TASK_UNINTERRUPTIBLE    (1 << 2)
#define TASK_ZOMBIE             (1 << 3)
#define TASK_STOPPED            (1 << 4)

#define CLONE_FS                (1 << 0)
#define CLONE_FILES             (1 << 1)
#define CLONE_SIGNAL            (1 << 2)

#define KERNEL_CS               (0x08)      // 内核代码段
#define KERNEL_DS               (0x10)      // 内核数据段
#define USER_CS                 (0x28)      // 用户代码段
#define USER_DS                 (0x30)      // 用户数据段

#define MAX_SYSTEM_CALL_NR      128         // 最大系统调用个数

// 定义在Kernel.lds中
extern char _text;
extern char _etext;
extern char _data;
extern char _edata;
extern char _rodata;
extern char _erodata;
extern char _bss;
extern char _ebss;
extern char _end;

extern unsigned long _stack_start;
extern void ret_from_intr();
extern void ret_system_call();
extern void system_call();

typedef struct __st_mm st_mm;
typedef struct __st_thread st_thread;

extern st_mm g_init_mm;
extern st_thread g_init_thread;

typedef struct __st_mm {
    pml4t_t *pgd;                           // 内存页表指针
    unsigned long start_code, end_code;     // 代码段空间
    unsigned long start_data, end_data;     // 数据段空间
    unsigned long start_rodata, end_rodata; // 只读数据段空间
    unsigned long start_brk, end_brk;       // 动态内存分配区（堆区域）
    unsigned long start_stack;              // 应用层栈基地址
} st_mm;

typedef struct __st_thread {
    unsigned long rsp0;                     // 内核层栈基地址
    unsigned long rip;                      // 内核层代码指针
    unsigned long rsp;                      // 内核层当前栈指针
    unsigned long fs;                       // fs段寄存器
    unsigned long gs;                       // gs段寄存器
    unsigned long cr2;                      // cr2控制寄存器
    unsigned long trap_nr;                  // 产生异常的异常号
    unsigned long error_code;               // 异常的错误码
} st_thread;

typedef struct {
    st_list list;                    // 双向链表，用于连接各个进程控制结构体
    volatile long state;                    // 进程状态：运行态、停止态、可中断态等
    unsigned long flags;                    // 进程标志：进程、线程、内核线程
    st_mm *mm;                       // 内存空间分布结构体，记录内存页表和程序段信息
    st_thread *thread;               // 进程切换时保留的状态信息
    unsigned long addr_limit;               // 进程地址空间范围
                                            /* 0x0000,0000,0000,0000 - 0x0000,7fff,ffff,ffff user */
                                            /* 0xffff,8000,0000,0000 - 0xffff,ffff,ffff,ffff kernel */
    long pid;                               // 进程id
    long counter;                           // 进程可用时间片
    long signal;                            // 进程持有的信号
    long priority;                          // 进程优先级
} st_task;

typedef union {
    st_task task;
    unsigned long stack[STACK_SIZE / sizeof(unsigned long)];
} un_task __attribute__((aligned(8)));               // 低地址保存st_task结构信息，高地址作为栈空间

#define TASK_INIT(tsk)  \
{   \
    .state = TASK_UNINTERRUPTIBLE,  \
    .flags = PF_KTHREAD, \
    .mm = &g_init_mm,   \
    .thread = &g_init_thread,   \
    .addr_limit = 0xffff800000000000,   \
    .pid = 0,   \
    .counter = 1,   \
    .signal = 0,    \
    .priority = 0   \
}

typedef struct __attribute__((packed)) {
    unsigned int reserved0;
    unsigned long rsp0;
    unsigned long rsp1;
    unsigned long rsp2;
    unsigned long reserved1;
    unsigned long ist1;
    unsigned long ist2;
    unsigned long ist3;
    unsigned long ist4;
    unsigned long ist5;
    unsigned long ist6;
    unsigned long ist7;
    unsigned long reserved2;
    unsigned short reserved3;
    unsigned short iomapbaseaddr;
} st_tss;

#define TSS_INIT    \
{   \
    .reserved0 = 0, \
    .rsp0 = (unsigned long)(g_init_task_union.stack + STACK_SIZE / sizeof(unsigned long)),  \
    .rsp1 = (unsigned long)(g_init_task_union.stack + STACK_SIZE / sizeof(unsigned long)),  \
    .rsp2 = (unsigned long)(g_init_task_union.stack + STACK_SIZE / sizeof(unsigned long)),  \
    .reserved1 = 0, \
    .ist1 = 0xffff800000007c00, \
    .ist2 = 0xffff800000007c00, \
    .ist3 = 0xffff800000007c00, \
    .ist4 = 0xffff800000007c00, \
    .ist5 = 0xffff800000007c00, \
    .ist6 = 0xffff800000007c00, \
    .ist7 = 0xffff800000007c00, \
    .reserved2 = 0, \
    .reserved3 = 0, \
    .iomapbaseaddr = 0  \
}

inline st_task *get_current();

#define CURRENT get_current()
// 
#define GET_CURRENT \
    "movq %rsp, %rbx \n\t"  \
    "andq $-32768, %rbx \n\t"

#define SWITCH_TO(prev, next)   \
do {    \
    __asm__ __volatile__ (  \
        "pushq %%rbp \n\t"  \
        "pushq %%rax \n\t"  \
        "movq %%rsp, %0 \n\t"   \
        "movq %2, %%rsp \n\t"	\
        "leaq 1f(%%rip), %%rax \n\t"	\
        "movq %%rax, %1	\n\t"	\
        "pushq %3 \n\t"	\
        "jmp __switch_to \n\t"	\
        "1: \n\t"   \
        "popq %%rax \n\t"	\
        "popq %%rbp \n\t"	\
        :"=m"(prev->thread->rsp), "=m"(prev->thread->rip)		\
        :"m"(next->thread->rsp), "m"(next->thread->rip), "D"(prev), "S"(next)	\
        :"memory"		\
    );  \
} while(0)

void task_init();

typedef unsigned long (*system_call_t)(st_pt_regs *);
unsigned long no_system_call(st_pt_regs *regs);
extern system_call_t g_system_call_table[MAX_SYSTEM_CALL_NR];

unsigned long sys_printf(st_pt_regs *regs);
#endif